﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using KinectTD.Towers;

namespace KinectTD.Agents
{
    public class Enemy
    {
        private Vector2 position;
        private float speedOriginal;
        private float speedActual;
        private float health;
        private Texture2D texture;
        private List<Tower> towers;
        private float radius;

        private int bounty;

        public int Bounty
        {
            get { return bounty; }
        }

        #region Animation

        public Vector2 Origin
        {
            get { return new Vector2(position.X + (size.X / 2), position.Y + (size.Y / 2)); }
        }


        private string currentAnimation = null; //String is empty

        public string CurrentAnimationName
        {
            get { return currentAnimation; }
            set { currentAnimation = value;  }
        }
        private bool isAnimating = true; //We're in an animated state

        #endregion
     

        private Vector2 size;

        public float Radius
        {
            get { return radius; }
        }

        public Vector2 Size
        {
            get { return size; }
            set { size = value; }
        }

        private Rectangle drawRect
        {
            get { return new Rectangle((int)position.X, (int)position.Y, (int)size.X, (int)size.Y); }
        }

        public Vector2 Position
        {
            get { return position; }
            set { position = value; }
        }

        public float Health
        {
            get { return health; }
            set { health = value;  }
        }

        public BULLET_TYPE weakness = BULLET_TYPE.NONE;
        public Dictionary<string, AnimationFrame> Animations = new Dictionary<string, AnimationFrame>(); //May as well be public - if we set it to private and use a getter you can just change the data anyway, serves no purpose and just slows thigns down


        private AnimationFrame CurrentAnimation
        {
            get
            {
                if (!string.IsNullOrEmpty(currentAnimation))
                {
                    return Animations[currentAnimation];
                }
                else return null;
            }

        }

        public Enemy(Vector2 enemyPosition, Texture2D enemyTexture, List<Tower> placedTowers) 
        {
           
            health = 100;
            bounty = (int)health;
            speedOriginal = 1.5f;
            speedActual = speedOriginal;
            position = enemyPosition;
            texture = enemyTexture;
            towers = placedTowers;
            size = new Vector2(enemyTexture.Width / 4, enemyTexture.Height);
            radius = size.X / 2;
            weakness = BULLET_TYPE.POISON;
           
           
        }


        public void Damage(float amount)
        {
            health -= amount;
        }

        public void Slow()
        {
            speedActual = speedOriginal / 2;
        }

        public void NormalSpeed()
        {
            speedActual = speedOriginal;
        }

        public void Update(GameTime gameTime)
        {
            

            if (position.X == Engine.GameViewport.Width)
            {
                position.X = 0;
                position.Y = Engine.GameViewport.Height / 2;
            }
            position.X += (1 * speedActual) * Engine.GAME_SPEED;

            foreach (Tower t in towers)
            {

                if (position.X <= t.Position.X + t.Radius && position.X >= t.Position.X - t.Radius)
                {
                    if (position.Y <= t.Position.Y + t.Radius + t.Size.Y / 2 && position.Y >= t.Position.Y - t.Radius)
                    {
                        if (position.Y >= t.Position.Y)
                        {
                            position.Y += (1 * speedActual) * Engine.GAME_SPEED;
                        }
                        if (position.Y < t.Position.Y)
                        {
                            position.Y -= (1 * speedActual) * Engine.GAME_SPEED;
                        }
                    }
                }
            }

            if (!isAnimating)
                return;

            AnimationFrame animation = CurrentAnimation;

            if (animation == null)
            {
                if (Animations.Count > 0)
                {
                    string[] keys = new string[Animations.Count];
                    Animations.Keys.CopyTo(keys, 0);

                    currentAnimation = keys[0];

                    animation = Animations[currentAnimation];
                }
                else
                {
                    return;
                }
            }
            animation.Update(gameTime);
            speedActual = speedOriginal;
        }


        public virtual void Draw(SpriteBatch spriteBatch)
        {

            AnimationFrame animation = CurrentAnimation;

            if (animation != null)
            {
                spriteBatch.Draw(texture, drawRect, animation.CurrentRectangle, Color.White);
            }
           

        }
    }

   public class AnimationFrame
    {
        #region DataMembers
        private Rectangle[] frames; //A collection of all the frames
        private int currentFrame; //What frame?
        private float frameLength; //FPS
        private float timer; //Used to calculate when to change frame
        #endregion

        #region Properties
        public int FramesPerSecond
        {
            get { return (int)(1f / frameLength); }
            set
            {
                frameLength = (float)Math.Max(1f / (float)value, .0001f); //In case we mess up, won't get it horribly slow
            }


        }

        public Rectangle CurrentRectangle
        {
            get { return frames[currentFrame]; }
        }

        public int CurrentFrame
        {
            get { return currentFrame; }
            set { currentFrame = (int)MathHelper.Clamp(value, 0, frames.Length - 1); } //Make sure it is a valid frame - we're going to be here for 24 hours, its going to be awful
        }
        #endregion

        public AnimationFrame(
            int numberOfFrames,
            int frameWidth,
            int frameHeight,
            int xOffset,
            int yOffset)
        {
            currentFrame = 0;
            frameLength = 0.5f;
            timer = 0;

            frames = new Rectangle[numberOfFrames];

            for (int i = 0; i < numberOfFrames; i++)
            {
                frames[i] = new Rectangle(xOffset + (i * frameWidth), yOffset, frameWidth, frameHeight);
            }
        }




        public void Update(GameTime gameTime)
        {
            timer += (float)gameTime.ElapsedGameTime.TotalSeconds * Engine.GAME_SPEED; //How many seconds?
            if (timer >= frameLength) //Do we need to change frame?
            {
                timer = 0; //Reset the timer
                currentFrame = (currentFrame + 1) % frames.Length; //Change the frame
            }
        }

    }
}
